package com.ruoyi.project.WxMoudle.api;

import com.google.common.collect.Maps;
import com.ruoyi.common.utils.OrderUtil;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.http.HttpUtils;
import com.ruoyi.common.utils.sms.SmsSendUtil;
import com.ruoyi.framework.interceptor.annotation.IgnoreAuth;
import com.ruoyi.project.WebMoudle.ShopSuser.domain.ShopSuser;
import com.ruoyi.project.WebMoudle.ShopSuser.service.IShopSuserService;
import com.ruoyi.project.WebMoudle.WxUser.domain.WxUser;
import com.ruoyi.project.WebMoudle.WxUser.service.IWxUserService;
import com.ruoyi.project.WebMoudle.onlineCoupon.domain.MyCoupon;
import com.ruoyi.project.WebMoudle.onlineCoupon.service.IOnlineCouponService;
import com.ruoyi.project.WebMoudle.shopPick.domain.ShopPick;
import com.ruoyi.project.WebMoudle.streamShop.service.IStreamShopService;
import com.ruoyi.project.WebMoudle.streamTerrace.domain.StreamTerrace;
import com.ruoyi.project.WebMoudle.streamTerrace.service.IStreamTerraceService;
import com.ruoyi.project.WebMoudle.terraceDetail.domain.TerraceDetail;
import com.ruoyi.project.WebMoudle.terraceDetail.service.ITerraceDetailService;
import com.ruoyi.project.WebMoudle.useTerms.domain.UseTerms;
import com.ruoyi.project.WebMoudle.useTerms.service.IUseTermsService;
import com.ruoyi.project.WebMoudle.userExchange.domain.UserExchange;
import com.ruoyi.project.WebMoudle.userExchange.service.IUserExchangeService;
import com.ruoyi.project.WebMoudle.userMessage.domain.UserMessage;
import com.ruoyi.project.WebMoudle.userMessage.service.IUserMessageService;
import com.ruoyi.project.WebMoudle.userPick.domain.UserPick;
import com.ruoyi.project.WebMoudle.userPick.service.IUserPickService;
import com.ruoyi.project.WebMoudle.vipCoupon.service.IVipCouponService;
import com.ruoyi.project.WxMoudle.Bases.*;
import com.ruoyi.project.alipay.OtherUtils;
import com.ruoyi.project.pickToBC.SendWeChat;
import com.sun.org.apache.xerces.internal.dom.PSVIAttrNSImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.HttpRequest;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.Console;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.time.LocalDate;
import java.time.LocalTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 用户逻辑
 */
@RestController
@RequestMapping(value = "/wx/VipUser")
public class VipUserController extends AppController {

    @Autowired
    private IWxUserService wxUserService;
    @Autowired
    private IShopSuserService shopSuserService;
    @Autowired
    private IVipCouponService vipCouponService;
    @Autowired
    private IUserPickService userPickService;
    @Autowired
    private IUseTermsService useTermsService;
    @Autowired
    private IUserExchangeService userExchangeService;
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    ;
    @Autowired
    private IStreamTerraceService streamTerraceService;
    @Autowired
    private IUserMessageService userMessageService;
    @Autowired
    private ITerraceDetailService terraceDetailService;


    /**
     * 微信公众号授权登录获取access_token
     */
    @RequestMapping(value = "/GetToken")
    @IgnoreAuth
    @ResponseBody
    public Object GetToken(String code) {
       /* WxUser wxUser = wxUserService.selectUserByOpId("o1WiwjvI1GFAiMD2jQMZsFWVuMnE");
//        WxUser wxUser = wxUserService.selectUserByOpId("321dfd3f13w3e131rf3e1");
        if (wxUser == null) {//该用户未授权
            return writeResultRep(null);
        } else {
            return writeResultRep(wxUser);
        }*/
        try {
            if (StringUtils.isEmpty(code)) {
                //账号密码未空
                return toResponsFail("code为空");
            } else {
                Object openId = redisTemplate.opsForValue().get(code);
                if (StringUtils.isNotNull(openId)) {   //缓存中存在此code(得到opnId查询是否注册 )
                    WxUser wxUser = wxUserService.selectUserByOpId((String) openId);
                    if (wxUser == null) {
                        System.out.println("缓存中新用户未授权");
                        return writeResultRep(null);
                    } else {
                        System.out.println("缓存中用户已授权过");
                        return writeResultRep(wxUser);
                    }
                }
                // 通过code获取网页授权凭证
                Wxoauth2token oauth2Token = WeixinHelper.getOauth2AccessToken(WeixinConfig.APPID, WeixinConfig.APPSECRET, code);
                //通过access_token调用微信后台接口获取到用户的信息
                if (oauth2Token == null) {
                    //没能获取到凭证
                    return toResponsFail("系统错误");
                }
                String hyOpenid = oauth2Token.getOpenId();
                redisTemplate.opsForValue().set(code, hyOpenid, 1, TimeUnit.DAYS);   //存入1天

                //通过openid查询用户对象
                WxUser wxUser = wxUserService.selectUserByOpId(hyOpenid);
                if (wxUser == null) {   //无此用户
                    System.out.println("无缓存新用户");
                    return writeResultRep(null);
                } else {   //存在用户
                    String access_token = oauth2Token.getAccessToken();
                    SNSUserInfo userInfo = WeixinHelper.getSNSUserInfo(access_token, hyOpenid);
                    for (int i = 0; i < 10; i++) {
                        System.out.println(userInfo);
                    }
                    wxUser.setNickName(userInfo.getNickname());
                    wxUser.setAvater(userInfo.getHeadImgUrl());//头像
                    wxUser.setSex(userInfo.getSex() + "");//性别
                    wxUserService.updateWxUser(wxUser);
                    System.out.println("无缓存用户已授权过");
                    return writeResultRep(wxUser);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            return toResponsFail("系统错误");
        }
    }


    /*保存手机号*/
    @RequestMapping(value = "/toPhone")
    @IgnoreAuth
    @ResponseBody
    public Object toPhone(String phoneNum, Long id) {

        WxUser user = new WxUser();
        user.setPhoneNum(phoneNum);
        user.setId(id);
        wxUserService.updateWxUser(user);
        WxUser wxUser = wxUserService.selectWxUserById(id);
        return writeResultRep(wxUser);
    }


    /*查询用户信息*/
    @RequestMapping(value = "/queryUser")
    @IgnoreAuth
    @ResponseBody
    public Object queryUser(Long userId) {

        WxUser wxUser = wxUserService.selectWxUserById(userId);
        return writeResultRep(wxUser);
    }

    /*查询用户金额及手续费*/
    @RequestMapping(value = "/queryUserMoney")
    @IgnoreAuth
    @ResponseBody
    public Object queryUserMoney(Long userId) {
        Map<Object, Object> map = new HashMap<>();
        WxUser wxUser = wxUserService.selectWxUserById(userId);
        UseTerms useTerms = useTermsService.selectUseTermsList(null).get(0);
        if (StringUtils.isNotNull(wxUser)) {
            map.put("ownMoney", wxUser.getOwnMoney());
        }
        map.put("userAdded", useTerms.getUserAdded());
        return map;
    }


    /*正式授权保存数据库*/
    @RequestMapping(value = "/toInsert")
    @IgnoreAuth
    @ResponseBody
    public Object toInsert(String code, Long shopId) {
        // 通过code获取网页授权凭证
        Wxoauth2token oauth2Token = WeixinHelper.getOauth2AccessToken(WeixinConfig.APPID, WeixinConfig.APPSECRET, code);
        //通过access_token调用微信后台接口获取到用户的信息
        if (oauth2Token == null) {
            //没能获取到凭证
            return toResponsFail("系统错误");
        }
        String hyOpenid = oauth2Token.getOpenId();
        String access_token = oauth2Token.getAccessToken();
        SNSUserInfo userInfo = WeixinHelper.getSNSUserInfo(access_token, hyOpenid);
        for (int i = 0; i < 10; i++) {
            System.out.println(userInfo);
        }
        //通过openid查询用户对象
        WxUser wxUser = wxUserService.selectUserByOpId(hyOpenid);
        if (wxUser != null) {
            wxUser.setNickName(userInfo.getNickname());
            wxUser.setAvater(userInfo.getHeadImgUrl());//头像
            wxUser.setSex(userInfo.getSex() + "");//性别
            wxUserService.updateWxUser(wxUser);
            return writeResultRep(wxUser);
        }
        if (userInfo == null) {
            return toResponsFail("未获取到用户信息");
        }
        WxUser user = new WxUser();
        user.setOpenId(oauth2Token.getOpenId());
        //不管是新用户保存还是老用户更新，都需要设置新获取到的用户信息
        user.setNickName(userInfo.getNickname());
        user.setAvater(userInfo.getHeadImgUrl());//头像
        user.setSex(userInfo.getSex() + "");//性别
        user.setIsVip("1");
        if (StringUtils.isNotNull(shopId)) {  //归属商家
            user.setShopId(shopId);
            user.setIsAlShop("1");
        }
        wxUserService.insertWxUser(user);

        return writeResultRep(user);
    }

    /*获取验证码*/
    @RequestMapping(value = "/getCode")
    @IgnoreAuth
    @ResponseBody
    public Object getCode(String phone) {
        try {
            String result = "";
            if (StringUtils.isNotEmpty(phone)) {    //是否传入手机号
                String phoneNumber = phone;
                Pattern p = Pattern.compile("^1[34578]\\d{9}$");
                Matcher m = p.matcher(phoneNumber);
                if (m.matches()) {
                    WxUser weiXinUser = new WxUser();
                    weiXinUser.setPhoneNum(phoneNumber);
                    List<WxUser> list = wxUserService.selectWxUserList(weiXinUser);
                    if (list != null && list.size() > 0) {    //验证手机号是否重复
                        Map<String, Object> map = new HashMap<String, Object>();
                        map.put("code", "1");
                        map.put("msg", "手机号已存在");
                        return map;
                    } else {
                        int ran = (int) (Math.random() * 9000) + 1000;
                        StringBuilder sb = new StringBuilder();
                        sb.append("accountSid").append("=").append(WeixinConfig.ACCOUNT_SID);
                        sb.append("&to").append("=").append(phoneNumber);
                        sb.append("&smsContent").append("=").append("【有有在线科技】您的验证码为:" + ran + "，请于5分钟内正确输入，如非本人操作，请忽略此短信。");
                        String body = sb.toString() + HttpUtil.createCommonParam(WeixinConfig.ACCOUNT_SID, WeixinConfig.AUTH_TOKEN);
                        result = HttpUtil.post(WeixinConfig.BASE_URL, body);

                        Map<String, Object> map = new HashMap<String, Object>();
                        map.put("code", ResultStatus.RESULT_STATUS_SUCCESS);
                        map.put("msg", CodeEnum.getName(ResultStatus.RESULT_STATUS_SUCCESS));
                        map.put("data", result);
                        map.put("ran", ran);
                        return map;
                    }
                } else {
                    Map<String, Object> map = new HashMap<String, Object>();
                    map.put("code", "1");
                    map.put("msg", "手机号格式有误");
                    return map;
                }

            } else {
                return writeResultFailure("电话号码不能为空！");
            }
        } catch (Exception e) {
            e.printStackTrace();
            return writeResultFailure("获取失败！");
        }
    }

    /*获取重置密码的手机验证码*/
    @RequestMapping(value = "/queryCode")
    @IgnoreAuth
    @ResponseBody
    public Object queryCode(String phone) {
        try {
            String result = "";
            if (StringUtils.isNotEmpty(phone)) {    //是否传入手机号
                String phoneNumber = phone;
                Pattern p = Pattern.compile("^1[34578]\\d{9}$");
                Matcher m = p.matcher(phoneNumber);
                if (m.matches()) {
                    int ran = (int) (Math.random() * 9000) + 1000;
                    StringBuilder sb = new StringBuilder();
                    sb.append("accountSid").append("=").append(WeixinConfig.ACCOUNT_SID);
                    sb.append("&to").append("=").append(phoneNumber);
                    sb.append("&smsContent").append("=").append("【有有在线科技】您的验证码为:" + ran + "，请于5分钟内正确输入，如非本人操作，请忽略此短信。");
                    String body = sb.toString() + HttpUtil.createCommonParam(WeixinConfig.ACCOUNT_SID, WeixinConfig.AUTH_TOKEN);
                    result = HttpUtil.post(WeixinConfig.BASE_URL, body);

                    Map<String, Object> map = new HashMap<String, Object>();
                    map.put("code", ResultStatus.RESULT_STATUS_SUCCESS);
                    map.put("msg", CodeEnum.getName(ResultStatus.RESULT_STATUS_SUCCESS));
                    map.put("data", result);
                    map.put("ran", ran);
                    return map;
                }
                Map<String, Object> map = new HashMap<String, Object>();
                map.put("code", "1");
                map.put("msg", "手机号格式有误");
                return map;
            } else {
                Map<String, Object> map = new HashMap<String, Object>();
                map.put("code", "1");
                map.put("msg", "手机号为空");
                return map;
            }
        } catch (Exception e) {
            e.printStackTrace();
            return writeResultFailure("获取失败！");
        }
    }

    /*查询我的消息数量*/
    @RequestMapping(value = "/myMessageCount")
    @IgnoreAuth
    @ResponseBody
    public Object myMessageCount(Long wxUserId) {
        System.out.println(wxUserId);
        int count = userMessageService.myMessageCount(wxUserId);
        return count;
    }

    /*查询我的全部消息*/
    @RequestMapping(value = "/queryMyMsgList")
    @IgnoreAuth
    @ResponseBody
    public Object queryMyMsgList(Long wxUserId) {
        List<UserMessage> list = userMessageService.queryMyMsgList(wxUserId);
        return list;
    }

    /*查询单一消息*/
    @RequestMapping(value = "/queryOneMsg")
    @IgnoreAuth
    @ResponseBody
    public Object queryOneMsg(Long umId) {
        UserMessage userMessage = userMessageService.selectUserMessageById(umId);
        return userMessage;
    }

    /*标记为已读*/
    @RequestMapping(value = "/markYiDu")
    @IgnoreAuth
    @ResponseBody
    public Object markYiDu(Long umId) {
        int i = userMessageService.markYiDu(umId);
        return i;
    }

    /*查询我的优惠券数量*/
    @RequestMapping(value = "/queryMyCouponNum")
    @IgnoreAuth
    @ResponseBody
    public Object queryMyCouponNum(Long wxUserId) {
        int count = vipCouponService.queryMyCouponNum(wxUserId);
        return count;
    }

    /*查询我的优惠券列表*/
    @RequestMapping(value = "/selectCouponList")
    @IgnoreAuth
    @ResponseBody
    public Object selectCouponList(Long wxUserId) {
        List<MyCoupon> list = vipCouponService.selectCouponList(wxUserId);
        return list;
    }

    /*根据金额可用优惠券列表*/
    @RequestMapping(value = "/selectUseList")
    @IgnoreAuth
    @ResponseBody
    public Object selectUseList(Long wxUserId, Double beforePrice) {
        //vipCouponService.updateExpire();
        List<MyCoupon> list = vipCouponService.selectUseList(wxUserId, beforePrice);
        return list;
    }

    /*积分兑换*/
    @RequestMapping(value = "/toExchange")
    @IgnoreAuth
    @ResponseBody
    @Transactional
    public Object toExchange(Long wxUserId, Integer exchangeJF) {
        WxUser user = wxUserService.selectWxUserById(wxUserId);
        if (user.getJiFen() - exchangeJF < 0) {
            return writeResultFailure("积分有误");
        }
        List<UseTerms> list = useTermsService.selectUseTermsList(null);
        UseTerms useTerms = list.get(0);
        user.setJiFen(user.getJiFen() - exchangeJF);   //减掉积分
        BigDecimal addMoney = new BigDecimal(exchangeJF.toString()).multiply(useTerms.getExchangeRatio());
        user.setOwnMoney(user.getOwnMoney().add(addMoney));   //增加余额
        /*记录积分转换明细*/
        UserExchange uec = new UserExchange();
        uec.setWxUserId(wxUserId);
        uec.setExchangeJf(exchangeJF);
        uec.setExchangeRatio(useTerms.getExchangeRatio());
        uec.setExchageMoney(addMoney.doubleValue());
        userExchangeService.insertUserExchange(uec);
        wxUserService.updateWxUser(user);   //更新用户信息
        WxUser wxUser = wxUserService.selectWxUserById(wxUserId);
        return writeResultRep(wxUser);
    }


    @RequestMapping(value = "/queryExchangeLog")
    @ResponseBody
    @IgnoreAuth
    @Transactional
    public Object queryExchangeLog(Long wxUserId, String month) {
        if (!StringUtils.isNotNull(wxUserId) || !StringUtils.isNotEmpty(month)) {
            return writeResultFailure("缺少参数传递");
        }

        List<UserExchange> list = userExchangeService.queryExchangeLog(wxUserId, month);
        return writeResultRep(list);
    }

    /*设置支付密码*/
    @RequestMapping(value = "/setPayNumber")
    @ResponseBody
    @IgnoreAuth
    @Transactional
    public Object setPayNumber(Long wxUserId, String payNumber) {

        int i = wxUserService.setPayNumber(wxUserId, payNumber);

        return writeResultRep();
    }


    /**
     * 用户提现到零钱
     *
     * @param pickMoney   提现金额
     * @param deductMoney 实际要扣除的金额
     * @param wxUserId
     * @return
     */
    @RequestMapping(value = "/toPickWechat")
    @ResponseBody
    @IgnoreAuth
    @Transactional
    public Object toPickWechat(BigDecimal pickMoney, BigDecimal deductMoney, Long wxUserId) {
        if (!StringUtils.isNotNull(pickMoney) || !StringUtils.isNotNull(wxUserId)) {
            return writeResultFailure("缺少参数传递");
        }
        WxUser wxUser = wxUserService.selectUserMoneyById(wxUserId);
        BigDecimal allMoney = wxUser.getOwnMoney();
        BigDecimal otherMoney = allMoney.subtract(deductMoney);     //用户扣除提现的账户余额
        if (otherMoney.doubleValue() < 0) {
            return writeResultFailure("账户余额不足");
        }
        UseTerms useTerms = useTermsService.selectUseTermsList(null).get(0);
        BigDecimal userAdded = useTerms.getUserAdded();
        String str = "";
        String OrderNum = OrderUtil.getGoodsOrderNo();
        try {
            /*进行提现*/
            str = toPickChange(pickMoney, wxUser.getOpenId(), OrderNum);    //提现到零钱的真实金额
            if (str.equals("fail")) {    //提现失败
                return writeResultFailure("提现失败");
            }
            //1.修改用户金额
            wxUser.setOwnMoney(otherMoney);
            wxUserService.updateWxUser(wxUser);     //修改金额
            //2.插入用户提现记录
            UserPick userPick = new UserPick();
            userPick.setOrderNum(OrderNum);
            userPick.setWxUserId(wxUserId);
            userPick.setPickMoney(pickMoney);
            userPick.setUserAdded(userAdded);
            userPickService.insertUserPick(userPick);
            //3.插入平台收入表
            StreamTerrace streamTerrace = new StreamTerrace();
            streamTerrace.setOrderNum(OrderNum);
            streamTerrace.setGainMoney(pickMoney.negate());
            streamTerrace.setGainType("用户提现" + pickMoney + "元");
            streamTerrace.setHandleType("2");
            streamTerraceService.insertStreamTerrace(streamTerrace);
            useTermsService.updateTerraceMoney(pickMoney.negate());
            //4.额外手续费
            if (userAdded.doubleValue() > 0) {    //收取额外手续费
                TerraceDetail terraceDetail = new TerraceDetail();
                terraceDetail.setOperateMoney(userAdded);
                terraceDetail.setOperateType("3");   //额外手续费
                terraceDetail.setHandleName(wxUser.getNickName());
                terraceDetailService.insertTerraceDetail(terraceDetail);        //插入平台账单
            }

        } catch (Exception e) {
            e.printStackTrace();
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
        }
        return writeResultRep(otherMoney);
    }


    @RequestMapping(value = "/queryMonthLog")
    @ResponseBody
    @IgnoreAuth
    @Transactional
    public Object queryMonthLog(Long wxUserId, String month) {
        if (!StringUtils.isNotNull(wxUserId) || !StringUtils.isNotEmpty(month)) {
            return writeResultFailure("缺少参数传递");
        }

        List<UserPick> list = userPickService.queryMonthLog(wxUserId, month);
        return writeResultRep(list);
    }


    /*==================================================静态方法的调用==========================================================================================*/
    /*提现到零钱的方法*/
    public String toPickChange(BigDecimal sumAmount, String openId, String OrderNum) throws Exception {

        //提现金额(单位:元)
        //元转换为分,微信支付已分为单位
        Map<String, String> map = Maps.newHashMap();
        //乘以100，转换为分
        BigDecimal transAmt = sumAmount.multiply(new BigDecimal("100"));

        //订单号
        map.put("partner_trade_no", OrderNum);
        map.put("mch_appid", WeixinConfig.APPID);
        map.put("mchid", WeixinConfig.MACHINEDID);
        map.put("check_name", "NO_CHECK");
        //随机字符串
        map.put("nonce_str", OtherUtils.getNonceStr().toString());
        map.put("spbill_create_ip", WeixinConfig.SPBILL_CREATE_IP);
        //openid("c从数据库中查询")
        map.put("openid", openId);
        //金额
        map.put("amount", Integer.toString(transAmt.intValue()));
        ////企业付款操作说明信息
        map.put("desc", "提现成功");

        //调用支付
        String returnInfo = SendWeChat.toWeChat(map, WeixinConfig.PAY_TO_PERON);
        Map<String, String> resultMap = OtherUtils.readStringXmlOut(returnInfo);
        if (resultMap.containsKey("result_code") && "SUCCESS".equals(resultMap.getOrDefault("result_code", ""))) {
            System.out.println("提现到零钱成功");
            System.out.println("返回结果：" + returnInfo);
            return "success";
        } else {
            System.out.println("提现到零钱失败");
            System.out.println("返回结果：" + returnInfo);
            return "fail";
        }

    }

    public static void main(String[] args) {
        System.out.println(new BigDecimal("2").negate().doubleValue() < 0);
    }
}
